[Xamarin.Forms] プログラムからJavaScriptを使用してgoogle検索を自動化する
1 プログラムからJavaScriptを操作する
ブラウザは、アプリの中で動作している場合に限り、コードからJavaScriptを実行したり、逆にJavaScriptからコードにアクセスすることが可能です。 今回は、Xamarin.FormsのWebViewでJavaScriptを実行することで、プログラムからGoogle検索をしてみました。
2 固有ブラウザ
Xamarin.Formsで使用するWebViewは、各プラットフォームごと動作しているブラウザが違うため、JavaScriptを実行する方法も異なります。 そこで、共通的に利用できるようにWebViewを拡張して、メソッドを1つ追加しました。 実際の実装は、レンダラーで行う事になります。
App.cs
public class ExWebView : WebView { public delegate void CallJsHandler(string js); public CallJsHandler CallJs;//JavaScriptの実行 }
3 レンダラー
続いて、各プラットフォームのレンダラーを実装します。
(1) iOS
iOSで動作しているUIKit.UIWebViewは、EvaluateJavascriptメソッドでJavaScript の実行が可能です。
ExWebViewRenderer.cs
using CallingJavascriptSample; using CallingJavascriptSample.iOS; using Xamarin.Forms; using Xamarin.Forms.Platform.iOS; using Xamarin.Forms.CallingJavascriptSample; [assembly: ExportRenderer(typeof(ExWebView), typeof(ExWebViewRenderer))] namespace CallingJavascriptSample.iOS { public class ExWebViewRenderer : WebViewRenderer { protected override void OnElementChanged(VisualElementChangedEventArgs e) { base.OnElementChanged(e); var exWebView = e.NewElement as ExWebView; if (exWebView!=null) { exWebView.CallJs = CallJs; } } public void CallJs(string js) { //this = UIKit.UIWebView //this.EvaluateJavascript(js); EvaluateJavascript(js); } } }
(2) Android
Androidで動作しているAndroid.Webkit.WebViewは、LoadUrl("javascript:" + js)でJavaScript の実行が可能です。
ExWebViewRenderer.cs
using Android.Webkit; using Xamarin.Forms.CallingJavascriptSample; using Xamarin.Forms.CallingJavascriptSample.Droid; using Xamarin.Forms; using Xamarin.Forms.Platform.Android; using WebView = Xamarin.Forms.WebView; [assembly: ExportRenderer(typeof(ExWebView), typeof(ExWebViewRenderer))] namespace Xamarin.Forms.CallingJavascriptSample.Droid { class ExWebViewRenderer:WebViewRenderer{ protected override void OnElementChanged(ElementChangedEventArgs<WebView> e){ base.OnElementChanged(e); var exWebView = e.NewElement as ExWebView; if (exWebView != null) { exWebView.CallJs = CallJs; } Control.SetWebChromeClient(new WebChromeClient()); } public void CallJs(string js){ //Android.Webkit.WebView Control.LoadUrl("javascript:" + js); } } }
4 JavaScriptの実行
それでは、この拡張ブラウザを使用して、JavaScriptを実行する画面を作成してみます。 Entryに入力された文字列をJavaScriptのコードとしてブラウザに送って実行するものです。
App.cs
namespace Xamarin.Forms.CallingJavascriptSample { public class App : Application { public App () { MainPage = new MyPage(); } } class MyPage : ContentPage { public MyPage() { var webView = new ExWebView() { Source = "http://www.google.com", VerticalOptions = LayoutOptions.FillAndExpand, }; var entry = new Entry() { HorizontalOptions = LayoutOptions.FillAndExpand }; var button = new Button { WidthRequest = 60, Text = "OK" }; button.Clicked += async (s, a) => { if (!string.IsNullOrEmpty(entry.Text)) { webView.CallJs(entry.Text); } }; Content = new StackLayout { Padding = new Thickness(0,Device.OnPlatform(20,0,0),0,0), Children = { new StackLayout { BackgroundColor = Color.Navy, Padding = 5, Orientation = StackOrientation.Horizontal, Children = { entry,button} },webView } }; } } }
実行画面は、次の通りです。alert()が実行されていることを確認できます。
5 IDの取得と動作確認
JavaScriptの実行が確認できたので、続いて、目的のgoogle検索に移ります。
まずは、Chromeの「要素の検証」を使用して、検索文字の入力位置、及び検索開始ボタンのid(name)を確認します。
↓idは「lst-ib」であることが分かる
↓nameは「btnG」であることが分かる
続いて、ChromeのデベロッパーツールのConsoleを使用して、JavaScriptの動作を確認しています。
//検索文字列に「123」をセットする document.getElementById('lst-ib').value='123'; //「検索」ボタンをクリックする document.getElementsByName('btnG')[0].click();
↓スクリプトが実行されて、意図する動作をしていることが確認できる。
6 アプリからの操作(Google検索)
目的の動作をするJavaScriptができたので、検索文字列をEntryから取得して、OKボタンでブラウザに送り込むようにしてみます。 修正したのはボタンのイベントハンドラだけです。
App.cs
button.Clicked += async (s, a) => { var js = string.Format("document.getElementById('lst-ib').value='{0}';",entry.Text); webView.CallJs(js); await Task.Delay(2000);//少しタイミングを計らないと、文字入力完了前にボタンを押してしまうためDelayを入れた js = "document.ElementsByName('btnG')[0].click();"; webView.CallJs(js); entry.Unfocus();//キーボード非表示 };
次の画面が動作している様子です。 ブラウザには触れずに検索を実行しています。
7 最後に
タイトルに自動化と書いてしまいましたが、今回のようにプログラムから制御できるとなれば、自動化も簡単でしょう。
最近は、各種のAPI等が公開されており、それらを駆使することで色々な機能を作り込むことが可能です。しかし、サービスによっては、どうしてもブラウザから実行するしかない作業も存在します。 そのような時、ブラウザを非表示にしてしまって、今回の手法でプログラムすれば、その制約をクリアできるかも知れません。
↓サンプルコードです。
https://github.com/furuya02/Xamarin.Forms.CallingJavascriptSample